ZF.add('plugin-switch', function(Z) {
    
    var E = Z.Event,
        F = Z.Function,
        D = Z.Dom,
        P = Z.Plugin,
        
        EVENT_TYPE_INIT = 'init',
        EVENT_TYPE_CHANGE = 'change',
        EVENT_TYPE_BEFORECHANGE = 'beforeChange',
        EVENT_TYPE_FOCUS = 'focus',
        EVENT_TYPE_ENTER = 'enter',
        EVENT_TYPE_LEAVE = 'leave',
        
        FIRE_EVENT = 'fireEvent',
        BIND_WITH_EVENT = 'bindWithEvent';


    var PS = P.Switchable = Z.create({

        init : function(options) {
            var self = this,
                triggers = [],
                panels = [],
                ops,
                container;

            self.setOptions(options, PS.defaults);
            
            ops = self.options;

            container = D.id(ops.container);

            if (container) {
                triggers = D.query('a', D.id(ops.container + '_t'));
                panels = D.query('div', D.id(ops.container + '_c'));
            } else {
                triggers = ops.triggers;
                panels = ops.panels;
            }

            self.triggers = Z.toArray(triggers);
            self.panels = Z.toArray(panels);

            self.size = self.panels.length;
            self.index = ops.index || 0;

            self._attachEvent();

            self[FIRE_EVENT](EVENT_TYPE_INIT);

            return self;
        },

        _attachEvent : function() {
            var self = this,
                ops = self.options,
                index = self.index,
                eType = ops.eType;

            Z.each(self.triggers, function(trigger, i) {
                // auto hide outline for A element
                if (trigger.tagName.toLowerCase() == 'a') {
                    D.hideOutline(trigger);
                }

                if (eType == 'focus') {
                    E.add(trigger, 'click', F[BIND_WITH_EVENT](self.onFocus, self, [i]));
                } else if (eType == 'move') {
                    E.adds(trigger, {
                        click : F[BIND_WITH_EVENT](function(e) { E.prevent(e); }),
                        mouseover : F[BIND_WITH_EVENT](self.onEnter, self, [i]),
                        mouseout : F[BIND_WITH_EVENT](self.onLeave, self, [i])
                    });
                }
            });
        },
        
        _isActived : function(index) {
            return this.index === index;
        },
        
        _clearTimer : function() {
            var self = this;
            self.timer = clearTimeout(self.timer);
            return self;
        },
        
        iSwitchTrigger : function(form, to) {
            var self = this,
                triggers = self.triggers,
                ops = self.options,
                cls = ops.cls;

            if (ops.replaceCls) {
                D.attr(triggers[form], 'class', cls.normal);
                D.attr(triggers[to], 'class', cls.active);
            } else {
                D.removeClass(triggers[form], cls).addClass(triggers[to], cls);
            }
        },
        
        iSwitchPanel : function(from, to) {
            var panels = this.panels;
            D.hide(panels[from]).show(panels[to]);
        },
        
        // 'click' or 'focus'
        onFocus : function(e, index) {
            E.prevent(e);
            var self = this;
            if (!self._isActived(index)) {
                self._clearTimer().to(index);
            }
            self[FIRE_EVENT](EVENT_TYPE_FOCUS, [index]);
        },
        
        onEnter : function(e, index, trigger) {
            E.prevent(e);
            var self = this;
            if (!self._isActived(index)) {
                self.timer = F.delay(function() {
                    self.to(index);
                }, self.options.delay || 100);
            }
            self[FIRE_EVENT](EVENT_TYPE_ENTER, [index]);
        },
        
        onLeave : function(e, index, trigger) {
            E.prevent(e);
            var self = this;
            if (!self._isActived(index)) {
                self._clearTimer();
            }
            self[FIRE_EVENT](EVENT_TYPE_LEAVE, [index]);
        },

        to : function(i) {
            var self = this, now = self.index;

            if (!self._isActived(i)) {

                if (self[FIRE_EVENT](EVENT_TYPE_BEFORECHANGE, [now, i]) !== false) {

                    self.iSwitchTrigger(now, i);

                    self.iSwitchPanel(now, i);

                    self[FIRE_EVENT](EVENT_TYPE_CHANGE, [now, i]);

                    self.index = i;

                }

            }

            return self;
        },

        prev : function() {
            var self = this, i = self.index;
            return self.to(i > 0 ? i - 1 : self.size - 1);
        },
        
        next : function() {
            var self = this, i = self.index;
            return self.to(i < self.size ? i + 1 : 0);
        }

    });

    PS.defaults = {

        // trigger switch by replace className redirectly
        //replaceCls : false,

        // auto hide outline for A element
        //hideOutline : true,

        // type of mouse event, can be 'focus'(click | focus) or 'move'(over | out)
        eType : 'focus',
        
        // switch delay time
        delay : 100,
        
        // className for active
        clsActive : 'actived'

    };

    Z.extend(PS.prototype, Z.Options, Z.Events);

}, { requires : ['plugin'] });